/*
   蜘蛛：抓取http://golangtc.com/内容，
   分析链接、翻页（最多10页），
   并发10个任务抓取新闻内容，内容传给另一个goroutine，由它负责保存到一个目录下(命名: <标题>.txt)
*/

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
	"sync"
)

type news struct {
	link    string
	title   string
	content string
}

const (
	indexURL = "http://golangtc.com"
)

var wg sync.WaitGroup

func main() {
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go getPageOfNum(i)
	}
	wg.Wait()
}

func getPageOfNum(page int) {
	urlStr := indexURL + "/?p=" + strconv.Itoa(page+1)
	pageCon := getWebContent(urlStr)
	newsReg := regexp.MustCompile("<a href=\"(.*?)\" class=\"title\">(.*?)</a>")
	newsSlice := newsReg.FindAllStringSubmatch(pageCon, -1)
	for i := 0; i < len(newsSlice); i++ {
		if link := newsSlice[i][1]; link != "" {
			linkStr := indexURL + "/" + link
			newsCon := getWebContent(linkStr)
			saveNews(newsCon)
		}
	}
	wg.Done()
}

//获取页面内容
func getWebContent(url string) (content string) {
	content = ""
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer resp.Body.Close()
	bodyData, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	content = string(bodyData)
	return
}

func saveNews(con string) {
	titleReg := regexp.MustCompile("<h1>(.*?)</h1>")
	aNews := new(news)
	titleSlice := titleReg.FindAllStringSubmatch(con, -1)
	if con := titleSlice[0][1]; con != "" {
		title := titleSlice[0][1]
		aNews.title = strings.Replace(title, "/", "-", -1)
	}
	re := regexp.MustCompile("\\<[\\S\\s]+?\\>")
	con = re.ReplaceAllStringFunc(con, strings.ToLower)
	//去除STYLE
	re = regexp.MustCompile("\\<style[\\S\\s]+?\\</style\\>")
	con = re.ReplaceAllString(con, "")
	//去除SCRIPT
	re = regexp.MustCompile("\\<script[\\S\\s]+?\\</script\\>")
	con = re.ReplaceAllString(con, "")
	//去除所有尖括号内的HTML代码，并换成换行符
	re = regexp.MustCompile("\\<[\\S\\s]+?\\>")
	con = re.ReplaceAllString(con, "\n")
	//去除连续的换行符
	re = regexp.MustCompile("\\s{2,}")
	con = re.ReplaceAllString(con, "\n")
	aNews.content = con
	aNews.writeToFile()
}

//写入文件 文件放在spider目录下
func (n *news) writeToFile() (done bool) {
	//判断文件夹是不是存在  不在创建文件夹
	filedir := "spider"
	_, err := os.Stat(filedir)
	if err != nil {
		err = os.Mkdir(filedir, 0777)
		if err != nil {
			fmt.Println("mkdir failed!")
			return
		}
	}
	//判断同名文件是否存在 存在打开 写入内容  不存在创建文件
	filePath := filedir + "/" + n.title + ".txt"
	dstFile, err := os.OpenFile(filePath, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer dstFile.Close()
	_, err = dstFile.WriteString(n.content)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	return true
}
